package cn.csc.framework.pay.core.client.dto;

import cn.csc.framework.pay.core.client.exception.PayException;
import cn.csc.framework.pay.core.enums.order.PayOrderStatusRespEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.util.Map;

/**
 * 统一下单 Response DTO
 *
 * @author
 */
@Accessors(chain = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class PayOrderUnifiedRespDTO {

    /**
     * 支付状态
     *
     * 枚举：{@link PayOrderStatusRespEnum}
     */
    private Integer status;

    /**
     * 展示模式
     */
    private String displayMode;
    /**
     * 展示内容
     * 通联：此处用于填充支付串（payinfo）
     */
    private String displayContent;

    /**
     * 商户订单号
     */
    private String merchantOrderNo;
    /**
     * 支付渠道交易单号 pay_order_extension的 no
     */
    private String tradeNo;

    /**
     * 调用渠道的错误码
     *
     * 注意：这里返回的是业务异常，而是不系统异常。
     * 如果是系统异常，则会抛出 {@link PayException}
     */
    private String channelErrorCode;
    /**
     * 调用渠道报错时，错误信息
     */
    private String channelErrorMsg;

    /**
     * 通联：rawData中的payinfo，其他支付目前为null
     */
    private Map<String,String> dataMap;
    /**
     * 支付渠道订单编号，同{@link PayOrderUnifiedRespDTO#tradeNo}
     * 拉卡拉：trade_no
     */
    private String channelOrderNo;
    /**
     * 支付渠道用户编号
     */
    private String channelUserId;

    /**
     * 支付成功时间,格式：yyyy-MM-dd HH:mm:ss
     */
    private String successTime;

    /**
     * 原始的同步/异步通知结果
     */
    private Object rawData;

    /**
     * 支付渠道商支付状态
     * TODO @jason 结合其他的渠道定义成枚举,
     * alipay
     * TRADE_CLOSED,未付款交易超时关闭，或支付完成后全额退款。
     * TRADE_SUCCESS, 交易支付成功
     * TRADE_FINISHED 	交易结束，不可退款。
     */
    private String tradeStatus;

    /**
     * 创建【WAITING】状态的订单返回
     */
    public static PayOrderUnifiedRespDTO waitingOf(String displayMode, String displayContent, String merchantOrderNo,
                                                   String tradeNo, Object rawData, Map<String,String> dataMap) {
        PayOrderUnifiedRespDTO respDTO = new PayOrderUnifiedRespDTO();
        respDTO.status = PayOrderStatusRespEnum.WAITING.getStatus();
        respDTO.displayMode = displayMode;
        respDTO.displayContent = displayContent;
        // 相对通用的字段
        respDTO.merchantOrderNo = merchantOrderNo;
        respDTO.tradeNo = tradeNo;
        respDTO.rawData = rawData;
        respDTO.dataMap = dataMap;
        return respDTO;
    }

    /**
     * 创建【SUCCESS】状态的订单返回
     */
    public static PayOrderUnifiedRespDTO successOf(String channelOrderNo, String channelUserId, String successTime,
                                          String tradeNo, String merchantOrderNo, Object rawData, Map<String,String> dataMap) {
        PayOrderUnifiedRespDTO respDTO = new PayOrderUnifiedRespDTO();
        respDTO.status = PayOrderStatusRespEnum.SUCCESS.getStatus();
        respDTO.channelOrderNo = channelOrderNo;
        respDTO.channelUserId = channelUserId;
        respDTO.successTime = successTime;
        respDTO.tradeNo = tradeNo;
        // 相对通用的字段
        respDTO.merchantOrderNo = merchantOrderNo;
        respDTO.rawData = rawData;
        respDTO.dataMap = dataMap;
        return respDTO;
    }

    /**
     * 创建指定状态的订单返回，适合支付渠道回调时
     */
    public static PayOrderUnifiedRespDTO of(Integer status, String channelOrderNo, String channelUserId, String successTime,
                                     String merchantOrderNo, Object rawData) {
        PayOrderUnifiedRespDTO respDTO = new PayOrderUnifiedRespDTO();
        respDTO.status = status;
        respDTO.channelOrderNo = channelOrderNo;
        respDTO.channelUserId = channelUserId;
        respDTO.successTime = successTime;
        // 相对通用的字段
        respDTO.merchantOrderNo = merchantOrderNo;
        respDTO.rawData = rawData;
        return respDTO;
    }

    /**
     * 创建【CLOSED】状态的订单返回，适合调用支付渠道失败时
     */
    public static PayOrderUnifiedRespDTO closedOf(String channelErrorCode, String channelErrorMsg,
                                           String merchantOrderNo, Object rawData) {
        PayOrderUnifiedRespDTO respDTO = new PayOrderUnifiedRespDTO();
        respDTO.status = PayOrderStatusRespEnum.CLOSED.getStatus();
        respDTO.channelErrorCode = channelErrorCode;
        respDTO.channelErrorMsg = channelErrorMsg;
        // 相对通用的字段
        respDTO.merchantOrderNo = merchantOrderNo;
        respDTO.rawData = rawData;
        return respDTO;
    }

}
